package com.alks.function.service.impl.stockdept.pcfactorystockquery;

import com.alibaba.excel.util.StringUtils;
import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.service.RedisService;
import com.alks.common.utils.beanutils.ArrayUtils;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.common.utils.beanutils.ObjectUtils;
import com.alks.entity.data.entity.*;
import com.alks.entity.data.enums.CompanyEnum;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.controller.finance.mtlcosts.OutListFinController;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.FdMtlSumDto;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.FdRqsDto;
import com.alks.function.data.request.stockdept.pcfactorystockwork.*;
import com.alks.function.data.vo.controller.stockdept.TypeConstants;
import com.alks.function.mapper.biocontrol.deptwork.PcSubOutLogMapper;
import com.alks.function.mapper.common.BackMapper;
import com.alks.function.mapper.pcfactoryquery.FT_QR_PcSlipDetailMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.*;
import com.alks.function.service.stockdept.pcfactorystockquery.IPcFitDegService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.alks.entity.data.enums.ResultCodeEnum.*;

@Service
@Slf4j
@RequiredArgsConstructor
public class PcFitDegServiceImpl extends ServiceImpl<SD_SQ_MpPurDisMapper, MpPurDis> implements IPcFitDegService {
    private final SD_SQ_PcLotUsageFitMapper fitMapper;
    private final SD_SQ_MpMtlLotMapper lotMapper;
    private final SD_SQ_MpMtlSumMapper sumMapper;
    private final SD_SQ_MpPurDisMapper disMapper;
    private final SD_SQ_MpMtlSubMapper subMapper;
    private final SD_SQ_MpPurMtlLotMapper mtlLotMapper;
    private final BackMapper backMapper;
    private final RedisService redisService;
    private final SD_SQ_PcMtlAccMapper accMapper;
    private final FT_QR_PcSlipDetailMapper slipMapper;
    private final PcSubOutLogMapper pcSubOutLogMapper;
    private final OutListFinController outListFinController;
    private final SD_SQ_PcMtlCheckMapper checkMapper;
//    private final PcLotHeadMapper lotHeadMapper;

    @Override
    @AutoPageAop
    public ResponseInfo getFdRqsQuery(FdRqsRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        /*获取数据*/
        List<FdRqsDto> dtos = fitMapper.getFdRqsQueryr(request,companyId);
        Page<FdRqsDto> page = (Page<FdRqsDto>) dtos;
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("dtos", dtos);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    @Transactional
    public ResponseInfo fdPurDisAdd(List<PurDisAddRequest> request) {
        /*获取基础数据*/

        String userName = UserIdThread.get().getUserName();
        String loginName = UserIdThread.get().getLoginName();
        String companyId = UserIdThread.get().getCompanyId();
        LocalDateTime now = LocalDateTime.now();
        request.forEach(r -> {r.setCompanyId(companyId);});
        /*判空*/
        if (request == null || request.isEmpty()) {
            return ResponseInfo.error("请选择要下单的数据", IN_IS_EMPTY.getCode());
        }
        /*生成请购单号*/
        String key = CompanyEnum.updateId(companyId) + "TH" + now.format(DateTimeFormatter.ofPattern("yyMM"));
        RedisAtomicInteger ato = new RedisAtomicInteger(key, redisService.getConnectionFactory());
        String value = String.format("%05d", ato.getAndIncrement());
        redisService.setOutTime(key);
        for (PurDisAddRequest r : request) {
            r.setReqNo(key + value);
        }
        /*写入数据*/
        disMapper.fdPurDisAdd(request, userName, now);
        sumMapper.fdPurDisAdd(request, userName, now, loginName);
        lotMapper.fdPurDisAdd(request, userName, now);
        subMapper.fdPurDisAdd(request);
        return ResponseInfo.ok("下单成功,请购单号：" + key + value);
    }

    @Override
    @AutoPageAop
    public Map<String, Object> getOrdQuery(OrdQueryRequest request) {
        /*获取用户数据*/
        String userName = UserIdThread.get().getUserName();
        /*查询数据*/
        List<MpPurDis> dis = lambdaQuery()
                .isNotNull(MpPurDis::getPurQty)
                .isNull(MpPurDis::getExpDate)
                .like(request.getPurNo() != null && !request.getPurNo().isEmpty(), MpPurDis::getPurNo, request.getPurNo())
                .like(StringUtils.isNotBlank(request.getMtlName()), MpPurDis::getMtlName, request.getMtlName())
                .like(StringUtils.isNotBlank(request.getPurLot()), MpPurDis::getPurLot, request.getPurLot())
                .eq(request.getPurType() != null && !request.getPurType().isEmpty(), MpPurDis::getPurType, request.getPurType())
                .eq(request.getVendorNo() != null && !request.getVendorNo().isEmpty(), MpPurDis::getVendorNo, request.getVendorNo())
                .like(request.getPurStyle() != null && !request.getPurStyle().isEmpty(), MpPurDis::getPurStyle, request.getPurStyle())
                .like(request.getPurColor() != null && !request.getPurColor().isEmpty(), MpPurDis::getPurColor, request.getPurColor())
                .like(request.getMtlType() != null && !request.getMtlType().isEmpty(), MpPurDis::getMtlNo, request.getMtlType())
                .le(request.getPurDateEnd() != null, MpPurDis::getPurDate, request.getPurDateEnd())
                .ge(request.getPurDateStart() != null, MpPurDis::getPurDate, request.getPurDateStart())
                /*选择模式*/
                .isNull(request.getFlag1() != null && request.getFlag1() == 1, MpPurDis::getPurFlag)
                .isNull(request.getFlag1() != null && request.getFlag1() == 2, MpPurDis::getExpDate)
                .isNotNull(request.getFlag1() != null && request.getFlag1() == 2, MpPurDis::getPurNo)
                .eq(request.getFlag1() != null && request.getFlag1() == 3, MpPurDis::getPurFlag, "Y")
                .eq(request.getFlag2() != null && request.getFlag2() == 1, MpPurDis::getSysUser, userName)
                /*固定组成*/
                .eq(MpPurDis::getPurType, "贴合")
                .likeRight(MpPurDis::getMtlNo, "N")
                .eq(MpPurDis::getCompanyId,UserIdThread.get().getCompanyId())
                .orderByDesc(MpPurDis::getReqNo)
                .list();
        List<MyOrdDto> dtos = BeanUtil.copyList(dis, MyOrdDto.class);
        /*补充分类数据*/
        for (MyOrdDto dto : dtos) {
            dto.setMtlType(backMapper.getMtlType(2, dto.getMtlNo().substring(0, 2)).get(0).get("typeName"));
        }
        /*封装数据*/
        Map<String, Object> map = new HashMap<>();
        map.put("dtos", dtos);
        if (!(request.getPageNum().equals(-1)||request.getPageSize().equals(-1))){
        Page<MpPurDis> page = (Page<MpPurDis>) dis;
        map.put("total", page.getTotal());
        }
        return map;
    }

    @Override
    public ResponseInfo getFdLotDetQuery(String reqNo, String purLot, String mtlNo) {
        /*查询数据*/
        LambdaQueryWrapper<MpMtlLot> wrapper = new LambdaQueryWrapper<MpMtlLot>()
                .eq(MpMtlLot::getReqNo, reqNo)
                .eq(MpMtlLot::getMtlNo, mtlNo)
                .eq(MpMtlLot::getLotNo, purLot);
        List<Map<String, Object>> dtos = lotMapper.selectList(wrapper)
                .stream().map(a -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("lotNo", a.getLotNo());
                    map.put("style", a.getStyle());
                    map.put("qty", a.getQty());
                    return map;
                }).collect(Collectors.toList());
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo getFdMtlSumQuery(String reqNo, String purLot, String mtlNo) {
        /*获取数据*/
        List<FdMtlSumDto> dtos = subMapper.getFdMtlSumQuery(reqNo, purLot, mtlNo);
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo myOrdUpdate(MyOrdUpRequest request) {
        /*获取数据*/
        MpPurDis dis = lambdaQuery().eq(MpPurDis::getCompanyId, request.getCompanyId())
                .eq(MpPurDis::getReqNo, request.getReqNo())
                .eq(MpPurDis::getPurLot, request.getPurLot())
                .eq(MpPurDis::getMtlNo, request.getMtlNo())
                .eq(MpPurDis::getSysUser, UserIdThread.get().getUserName())
                .select(MpPurDis::getQty, MpPurDis::getPurFlag)
                .one();
        /*判断数据是否存在*/
        if (dis == null || dis.getQty() == null) {
            log.error("请求方法：myOrdUpdate\n错误原因：没有找到数据\n请求参数：reqNo:{}  purNo:{}  lotNo:{}",
                    request.getReqNo(), request.getPurNo(), request.getPurLot());
            return ResponseInfo.error("数据异常，请联系后台管理", DATA_IS_ERR.getCode());
        }
        /*更新数据*/
        float purQty = dis.getQty() +
                (request.getMinusQty() == null ? 0 : request.getMinusQty()) +
                (request.getOverQty() == null ? 0 : request.getOverQty());
        lambdaUpdate().eq(MpPurDis::getCompanyId, request.getCompanyId())
                .eq(MpPurDis::getReqNo, request.getReqNo())
                .eq(MpPurDis::getPurLot, request.getPurLot())
                .eq(MpPurDis::getMtlNo, request.getMtlNo())
                .eq(MpPurDis::getSysUser, UserIdThread.get().getUserName())
                /*如果已下单则不能修改*/
                .set(dis.getPurFlag() == null || !"Y".equals(dis.getPurFlag()), MpPurDis::getVendorNo, request.getVendorNo())
                .set(dis.getPurFlag() == null || !"Y".equals(dis.getPurFlag()), MpPurDis::getVendorName, request.getVendorName())
                .set(dis.getPurFlag() == null || !"Y".equals(dis.getPurFlag()), MpPurDis::getPurMemo, request.getPurMemo())
                .set(MpPurDis::getOverQty, request.getOverQty())
                .set(MpPurDis::getMinusQty, request.getMinusQty())
                .set(MpPurDis::getVendorDate, request.getVendorDate())
                .set(MpPurDis::getInDate, request.getInDate())
                .set(MpPurDis::getPurQty, purQty)
                .update();
        return ResponseInfo.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseInfo creatPurUpdate(List<MyOrdUpRequest> request) {
        /*准备数据*/
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        String userName = tokenDTO.getUserName();
        String subType = "N";
        LocalDateTime now = LocalDateTime.now();
        /*禁止重复生成订购单*/
        /*生成订购单*/
        String key = request.get(0).getCompanyId() + "P" + now.format(DateTimeFormatter.ofPattern("yyMM"));
        RedisAtomicInteger ato = new RedisAtomicInteger(key, redisService.getConnectionFactory());
        String value = String.format("%05d", ato.getAndIncrement());
        redisService.setOutTime(key);
        for (MyOrdUpRequest r : request) {
            r.setPurNo(key + value);
        }
//        /*贴合出库*/
//        List<MyOrdUpRequest> subList = request.stream().filter(a -> a.getMtlNo().startsWith(subType)).collect(Collectors.toList());
//        if (ArrayUtils.isNoEmpyt(subList)){
//            // 获取贴合子材料数据
//            List<PcSubOutLog> logList = fitMapper.getFitMtl(subList,companyId);
//            if (ArrayUtils.isEmpyt(logList)){
//                throw new ServiceErrorException("贴合子材料建档异常");
//            }
//            // 找出库存不足的数据
//            List<PcMtlAcc> accList= accMapper.findStkMiss(logList,companyId);
//            if (ArrayUtils.isEmpyt(accList)){
//                throw new ServiceErrorException("仓库中没有这些子材料");
//            }
//            Map<String, BigDecimal> map = accList.stream().collect(Collectors.toMap(a -> (a.getMtlNo() + a.getMtlName() + a.getMtlColor() + a.getMtlColor() + a.getMtlSpec() + a.getMtlUnit()), PcMtlAcc::getStkQty));
//            for (PcSubOutLog outLog : logList) {
//                String mtlKey = outLog.getMtlNo() +outLog.getMtlName() +outLog.getMtlColor() + outLog.getMtlColor() + outLog.getMtlSpec() + outLog.getMtlUnit();
//                if (map.get(mtlKey) == null || map.get(mtlKey).compareTo(outLog.getQty())<0) {
//                    throw new ServiceErrorException(outLog.getMtlName()+"库存不足");
//                }
//            }
//            for (PcSubOutLog log : logList) {
//                log = log
//                        .setPurNo(key + value)
//                        .setSysUser(userName)
//                        .setSysDate(LocalDateTime.now())
//                        .setCompanyId(companyId)
//                        .setType(TypeConstants.FitSubStatus.IN);
//                pcSubOutLogMapper.insert(log);
//                accMapper.subFitMtlUp(log,companyId);
//            }
//        }
        /*更新订单和贴合数据*/
        disMapper.creatPurUpdate(request);
        subMapper.creatPurUpdate(request);
        /*写入订单表*/
        mtlLotMapper.creatPurUpdate(request);
        return ResponseInfo.ok(key + value);
    }

    @Override
    @Transactional
    public ResponseInfo fdMtlSumUpdate(List<MtlSumUpRequest> request, Integer flag) {
        if (flag==null||flag!=2){
            subMapper.fdMtlSumUpdate1(request);
            return ResponseInfo.ok();
        }
        if (request==null||request.isEmpty()){
            return ResponseInfo.error("请选择数据",IN_IS_EMPTY.getCode());
        }
        /*筛选掉不需要的数据*/
        request = request.stream().filter(a -> a.getPurFlag()==null||!"Y".equals(a.getPurFlag())).collect(Collectors.toList());
        if (request.isEmpty()){
            return ResponseInfo.error("没有实际需要出库的数据", INPUT_ERROR.getCode());
        }
        for (MtlSumUpRequest r : request) {
            if (r.getQty()==null||r.getQty().equals(BigDecimal.ZERO)){
                return ResponseInfo.error("存在出库数量为空", INPUT_ERROR.getCode());
            }
        }
        /*提取mtlNo和对应数量  【lotNo筛选注释掉了】*/
        Map<String, BigDecimal> qtyMap = request.stream()
                .collect(Collectors.toMap(a -> a.getMtlNoUp() == null || a.getMtlNoUp().isEmpty() ? a.getMtlNo() : a.getMtlNoUp(),
                        MtlSumUpRequest::getQty));
        List<String> mtlNos = new ArrayList<>(qtyMap.keySet());
//        List<String> lotNos = request.stream()
//                .map(MtlSumUpRequest::getPurLot)
//                .collect(Collectors.toList());
        /*判断数据是否存在*/
        LambdaQueryWrapper<PcMtlAcc> mtlWrapper = new LambdaQueryWrapper<PcMtlAcc>()
                .select(PcMtlAcc::getStkQty, PcMtlAcc::getMtlNo)
                .in(PcMtlAcc::getMtlNo, mtlNos);
        Map<String, BigDecimal> stkMap = accMapper.selectList(mtlWrapper).stream()
                .collect(Collectors.toMap(PcMtlAcc::getMtlNo, PcMtlAcc::getStkQty));
        for (String mtlNo : mtlNos) {
            if (stkMap.get(mtlNo) == null) {
                return ResponseInfo.error("不存在的物料号：" + mtlNo, INPUT_ERROR.getCode());
            }
            if (stkMap.get(mtlNo).compareTo(qtyMap.get(mtlNo))<0) {
                return ResponseInfo.error("物料号：" + mtlNo + "\n库存量不足", INPUT_ERROR.getCode());
            }
        }
//        LambdaQueryWrapper<PcLotHead> lotWrapper=new LambdaQueryWrapper<PcLotHead>()
//                .select(PcLotHead::getLotNo)
//                .in(PcLotHead::getLotNo,lotNos);
//        Map<String, Object> lotMap = lotHeadMapper.selectList(lotWrapper).stream().collect(Collectors.toMap(PcLotHead::getLotNo, null));
//        for (String lotNo : lotNos) {
//            if (lotMap.containsKey(lotNo)){
//                return ResponseInfo.error("指令不存在：\n"+lotNo)
//            }
//        }
        /*获取基础数据*/
        LocalDateTime now = LocalDateTime.now();
        String userName = UserIdThread.get().getUserName();
        int i = 1;
        for (MtlSumUpRequest r : request) {
            r.setItem(i);
            i++;
        }
        String key = request.get(0).getCompanyId() + "Q" + now.format(DateTimeFormatter.ofPattern("yyMM"));
        RedisAtomicInteger ato = new RedisAtomicInteger(key, redisService.getConnectionFactory());
        String slipNo = key + String.format("%05d", ato.getAndIncrement());
        redisService.setOutTime(key);
        /*写入发料明细*/
        slipMapper.fdMtlSumUpdate(request, now, userName, slipNo);
        /*更新库存*/
        accMapper.fdMtlSumUpdate(request);
        /*更新贴合数据*/
        subMapper.fdMtlSumUpdate(request, slipNo);
        return ResponseInfo.ok("出库完成");
    }

    @Override
    @Transactional
    public ResponseInfo fdMtlSumCancel(String slipNo) {
        /*判断是否出库*/
        if (ObjectUtils.isEmpty(slipNo)) {
            return ResponseInfo.error("还没有出库", IN_IS_EMPTY.getCode());
        }
        /*判断出库单号是否正确*/
        LambdaQueryWrapper<MpMtlSub> wrapper = new LambdaQueryWrapper<MpMtlSub>()
                .select(MpMtlSub::getMtlNo,MpMtlSub::getQty)
                .eq(MpMtlSub::getSlipNo, slipNo);
        List<Map<String,Object>> mtlNo = subMapper.selectList(wrapper).stream().
                map(a->{Map<String,Object> map=new HashMap<>();
                        map.put("qty",a.getQty());
                        map.put("mtlNo",a.getMtlNo());
                        return map;}).
                collect(Collectors.toList());
        /*回滚数据*/
        slipMapper.fdMtlSumCancel(slipNo);
        accMapper.fdMtlSumCancel(mtlNo);
        subMapper.fdMtlSumCancel(slipNo);
        return null;
    }

    @Override
    public ResponseInfo getFitReamarkQuery() {
        List<String> dtos = disMapper.getFitReamarkQuery();
        return ResponseInfo.ok(dtos);
    }

    @Override
    public List<MyOrdDto> getExportByPurNo(List<String> purNoList) {
        /*获取用户数据*/
        String userName = UserIdThread.get().getUserName();
        /*查询数据*/
        List<MpPurDis> dis = lambdaQuery()
                .isNotNull(MpPurDis::getPurQty)
                .isNull(MpPurDis::getExpDate)
                .in(MpPurDis::getPurNo,purNoList)
                .eq( MpPurDis::getSysUser, userName)
                .eq(MpPurDis::getPurType, "贴合")
                .likeRight(MpPurDis::getMtlNo, "N")
                .eq(MpPurDis::getCompanyId,UserIdThread.get().getCompanyId())
                .orderByDesc(MpPurDis::getReqNo)
                .list();
        List<MyOrdDto> dtos = BeanUtil.copyList(dis, MyOrdDto.class);
        /*补充分类数据*/
        for (MyOrdDto dto : dtos) {
            dto.setMtlType(backMapper.getMtlType(2, dto.getMtlNo().substring(0, 2)).get(0).get("typeName"));
        }
        return dtos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void getPurBack(Integer id) {
        // 获取要退库数据
        LambdaUpdateWrapper<MpPurDis> wrapper = new LambdaUpdateWrapper<MpPurDis>()
                .eq(MpPurDis::getId, id);
        MpPurDis dis = baseMapper.selectOne(wrapper);

        // 校验是否满足退库条件
        LambdaQueryWrapper<PcMtlCheck> checkWrapper = new LambdaQueryWrapper<PcMtlCheck>()
                .eq(PcMtlCheck::getPurLot, dis.getPurLot())
                .eq(PcMtlCheck::getPurNo, dis.getPurNo())
                .eq(PcMtlCheck::getReqNo,dis.getReqNo())
                .eq(PcMtlCheck::getMtlNo, dis.getMtlNo())
                .eq(PcMtlCheck::getMtlName,dis.getMtlName())
                .eq(StringUtils.isNotBlank(dis.getMtlColor()),PcMtlCheck::getMtlColor,dis.getMtlColor())
                .isNull(StringUtils.isBlank(dis.getMtlColor()),PcMtlCheck::getMtlColor)
                .eq(StringUtils.isNotBlank(dis.getMtlUnit()),PcMtlCheck::getMtlUnit,dis.getMtlUnit())
                .isNull(StringUtils.isBlank(dis.getMtlUnit()),PcMtlCheck::getMtlUnit)
                .eq(StringUtils.isNotBlank(dis.getMtlSpec()),PcMtlCheck::getMtlSpec,dis.getMtlSpec())
                .isNull(StringUtils.isBlank(dis.getMtlSpec()),PcMtlCheck::getMtlSpec)
                .eq(PcMtlCheck::getCompanyId, dis.getCompanyId());
        Integer count = checkMapper.selectCount(checkWrapper);
        if (count>0){
            throw new ServiceErrorException("已有收料信息，不能退单");
        }

        // 回滚数据
        wrapper.set(MpPurDis::getOverQty,null)
                .set(MpPurDis::getMinusQty,null)
                .set(MpPurDis::getVendorName,null)
                .set(MpPurDis::getVendorNo,null)
                .set(MpPurDis::getVendorDate,null)
                .set(MpPurDis::getInDate,null)
                .set(MpPurDis::getPurMemo,null)
                .set(MpPurDis::getPurNo,null)
                .set(MpPurDis::getPurDate,null)
                .set(MpPurDis::getPurFlag,null)
                .set(MpPurDis::getReqMemo,null);
        baseMapper.update(null, wrapper);
        subMapper.purBack(dis);
        mtlLotMapper.purBack(dis);


    }


}
